# -*- coding: utf-8 -*-
import json
import logging
import os
import time

import re

import pandas as pd
import requests
import yaml
from openai import OpenAI
import numpy as np

from kumquat_king_pyside6.app_config import CONFIG_FILE


def basic_log_config(logDir, debug=True):
    """
    日志输出格式设定
    :param debug: 是否为DEBUG模式
    :return:
    """
    LOG_FORMAT = "%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)d - %(message)s"
    DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
    if debug:
        logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT)
    else:
        logFilename = os.path.join(logDir, time.strftime("%Y_%m_%d", time.localtime()) + '.log')
        logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, filename=logFilename,
                            filemode='a')
    # for handler in logging.root.handlers:
    #     handler.addFilter(logging.Filter('main.py'))


def load_yaml(filepath=CONFIG_FILE):
    """
    加载yaml配置文件
    :param filepath:
    :return:
    """
    try:
        with open(filepath, 'r') as f:
            data = yaml.load(f, Loader=yaml.SafeLoader)
            return data
    except Exception as e:
        raise Exception(f"Error loading yaml file: {filepath}")


def message_box(title, msg):
    """
    # 桌面弹出消息框
    # Python弹出Windows自带的MessageBox
    :param title:
    :param msg:
    :return:
    """
    import ctypes
    ctypes.windll.user32.MessageBoxW(0, msg, title, 1)


phone_pattern = re.compile(r'(\+?86[-\s]?)?(1[3-9]\d{9})')
"""
规则：
金桔和名字必须有逗号隔开
金桔必须为1-9箱的形式
"""

GUESS_ORDER_HEADERS = ['customer_name', 'customer_addr', 'customer_phoneNumber', 'kumquat_name', 'kumquat_format',
                       'quantity', 'on_sold', 'presenter', 'note']


def identify_orders(order_str: str):
    """
    Expected format:
    {customer_name, customer_addr, customer_phoneNumber,  \
                          kumquat_name, kumquat_format, quantity, on_sold, presenter, note}
    Test sample:
    卡门	北京市 朝阳区 梵谷水郡7号楼3单元603	15602290420	脆蜜4号	5斤装	1	1	ME
    王晓艳老师	北京朝阳区阳坊8号院9号楼三单元1201	13681005343	脆蜜2号	3斤装	1	1	cddc
    谢某	开源大道11号广州开发区科技企业加速器B7栋五楼	18298361737	脆蜜4号	3斤装	1	1	ME

    :param order_str:
    :return:
    """
    rawOrderLine = order_str.lstrip().rstrip().split("\n")

    guessSpliter = guess_spliter(rawOrderLine[0])
    logging.info(f"Guessed spliter: {repr(guessSpliter)}")
    rawOrders = [line.split(guessSpliter) for line in rawOrderLine]
    expected_length = len(GUESS_ORDER_HEADERS)
    for i in range(len(rawOrders)):
        if len(rawOrders[i]) < expected_length:
            rawOrders[i].extend([np.nan] * (expected_length - len(rawOrders[i])))
        elif len(rawOrders[i]) > expected_length:
            rawOrders[i] = rawOrders[i][:expected_length]

    rawDf = pd.DataFrame(rawOrders, columns=GUESS_ORDER_HEADERS)
    # resDF = pd.DataFrame(columns=GUESS_ORDER_HEADERS)
    # guessColMappings = guess_columns(rawDf)
    # print(f"Guessed mappings: {guessColMappings}")
    return rawDf


def guess_spliter(text):
    spliters = [' ', '\r', '\t', ',', ':', '|']
    splitedLen = []
    for spliter in spliters:
        splitedLen.append(text.count(spliter))
    return spliters[splitedLen.index(max(splitedLen))]


def guess_columns(rawDf):
    mapper = {'customer_name': [0, False], 'customer_addr': [1, False], 'customer_phoneNumber': [2, False],
              'kumquat_name': [3, False], 'kumquat_format': [4, False],
              'quantity': [5, False], 'on_sold': [6, False], 'presenter': [7, False], 'note': [8, False]}
    if len(rawDf.columns) < 3:
        raise ValueError(f"Unable to parse the data, length < 3: f{rawDf.columns}")
    print(rawDf.columns)
    for col in rawDf.columns:
        isAddr = rawDf[col].str.contains('省|市|区|县|栋|楼')
        # print(f"addr - {rawDf[col]}, isAddr -{isAddr}")
        if isAddr.all() and not mapper['customer_addr'][1]:
            mapper['customer_addr'] = col, True
        cleanedCol = rawDf[col].str.replace(' ', '').str.replace('-', '')
        isPhoneNumber = cleanedCol.str.len() == 11
        if isPhoneNumber.all() and not mapper['customer_phoneNumber'][1]:
            mapper['customer_phoneNumber'] = col, True
        isName = rawDf[col].str.len().between(2, 5)
        outKumquat = rawDf[col].str.contains('滑皮|脆蜜')
        if isName.all() and not outKumquat.all() and not mapper['customer_name'][1]:
            mapper['customer_name'] = col, True
        elif isName.all() and mapper['customer_name'][1] and not mapper['presenter']:
            mapper['presenter'] = col, True
        isKumquatName = rawDf[col].str.contains('滑皮|脆蜜')
        if isKumquatName.all() and not mapper['kumquat_name'][1]:
            mapper['kumquat_name'] = col, True
        isKumquatFormat = rawDf[col].str.contains('斤装')
        if isKumquatFormat.all() and not mapper['kumquat_format'][1]:
            mapper['kumquat_format'] = col, True
        isQuantity = rawDf[col].apply(lambda x: isinstance(x, int)).all()
        print(f"isQuantity - {isQuantity}, row - {rawDf[col]}")
        if isQuantity and not mapper['quantity'][1]:
            mapper['quantity'] = col, True
        isOnSold = rawDf[col].apply(lambda x: isinstance(x, float)).all()
        if isOnSold and not mapper['on_sold'][1]:
            mapper['on_sold'] = col, True
        isNote = rawDf[col].isna().any() or rawDf[col].str.contains('赠送').any()
        if isNote and not mapper['note'][1]:
            mapper['note'] = col, True
    return mapper


def clean_string(text):
    res = text.strip().replace('。', ' ').replace('，', ', ').replace('（', ' ').replace('）', ' ').replace('`',
                                                                                                        '').replace(
        'json', '')
    return res


def openai_query(question):
    client = OpenAI(api_key=API_KEY, base_url=OPENAI_BASE_URL)

    res = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant to help me convert the order data."},
            {"role": "user", "content": f"{question}"},
        ],
    )
    return res.choices[0].message.content


def get_ollama_models(host):
    url = f"{host}/api/tags"
    try:
        response = requests.get(url)
        if response.status_code == 200:
            models = response.json().get('models', [])
            return models
        else:
            logging.error(f"Error: {response.status_code}, {response.text}")
            return []
    except requests.RequestException as e:
        logging.error(f"Request Ollama error: {e}")
        return []


def request_ollama(host, prompt, model):
    logging.info(f"Requesting Ollama API...{prompt}")
    url = f"{host}/api/chat"
    headers = {
        'Content-Type': 'application/json',
    }
    data = {
        'model': model,
        'messages': [
            {'role': 'system', 'content': 'You are a helpful assistant to help me convert the order data.'},
            {'role': 'user', 'content': prompt}
        ],
        'stream': False
    }
    try:
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            result = response.json()
            logging.info("Ollama API Response:", result['message']['content'])
            return result['message']['content']
        else:
            logging.error("Error:", response.status_code, response.text)
    except Exception as e:
        logging.error("Error:" + str(e))


# prompt = """
# 1、广州市黄埔区黄埔东路佳兆业城市广场114 A-507，陈小丽 13924175346（1箱）
# 2、广州市天河区粤垦路105号百姓百味海鲜酒楼。13802516323李明（8箱）
# 3、广州市海珠区海联路东翠花园晓怡阁32号梁小姐13660046139（1箱）
# 整理这段文字为json格式，格式为 姓名，地址，电话，并以json格式返回，不要说其他的话。
# """
# request_ollama("http://localhost:11434", prompt, "qwen2.5-coder:7b")


def handle_orders_df(ordersJson):
    orders = json.loads(ordersJson)
    custJson = []
    for order in orders:
        custJson.append({
            "name": order['customer_name'],
            "phoneNumber": order['customer_phoneNumber'],
            "address": order['customer_addr'],
            "presenter": order['customer_presenter']
        })
    return ordersJson, json.dumps(custJson, ensure_ascii=False)


def kumquat_format_converter(kumquat_str: str, flag='ZH2ST'):
    if flag == 'ZH2ST':
        kumquatName, kumquatStyle = kumquat_str.split(' ')
        if kumquatStyle[0].isdigit():
            kumquatStyle = kumquatStyle.replace('斤装', '')
            return kumquatName, kumquatStyle
        else:
            raise ValueError('Invalid kumquat format')
    else:
        return kumquat_str + '斤装'
